import math
import select
import os
import shutil
import maya.cmds as cmds
import maya.mel as mel

def asScriptLocatorProc():
	pass


def asGetScriptLocation():
	whatIs = mel.eval('whatIs asScriptLocatorProc')
	fullPath = whatIs[25:]
	buffer = fullPath.split("/")
	numLetters = len(fullPath)
	numLettersLastFolder = len(buffer[-1])
	scriptLocation = fullPath[0:(numLetters - numLettersLastFolder - 1)]
	return scriptLocation


def asEnsureAsGetScriptLocation():
	asSelectorScriptLocation = ""
	AdvancedSkeletonMelFile = ""
	folders = []
	if "asGetScriptLocation" in globals():
		return
	elif "asSelectorScriptLocation" in globals():
		asSelectorScriptLocation = asSelectorScriptLocation
		if asSelectorScriptLocation.startswith("/AdvancedSkeletonFiles/"):
			AdvancedSkeletonMelFile = asStripPath(asSelectorScriptLocation , 2) + "AdvancedSkeleton.mel"
			if os.path.isfile(AdvancedSkeletonMelFile):
				cmds.evalDeferred('"source "'" + AdvancedSkeletonMelFile + "'')
				print("source "" + AdvancedSkeletonMelFile + "";\n")
				cmds.error("AdvancedSkeleton.mel was not sourced. Sourcing this now. Try running this function again")
			else:
				cmds.error("Expected file not found: " + AdvancedSkeletonMelFile)
		else:
			cmds.error("Seems AdvancedSkeleton is not installed (only running Selector or Picker). This function requires AdvancedSkeleton installed.\n")
	else:
		cmds.error("Unable to run asGetScriptLocation, and unable to run asSelectorScriptLocation, so unable to determine directory for force-aligner.")


def asSelectorScriptLocation():
	whatIs = mel.eval('whatIs asSelectorScriptLocation')
	fullPath = whatIs[25:]
	buffer = fullPath.split("/")
	numTok = len(fullPath)
	print
	numTok
	if numTok < 2:
		if mel.eval('about -win'):
			buffer = fullPath.split("/")
			print
			buffer
	numLetters = len(fullPath)
	numLettersLastFolder = len(buffer[-1])
	scriptLocation = fullPath[:numLetters - numLettersLastFolder]
	return scriptLocation


def asAutoLipSyncLanguages():
	languages = ["Bulgarian" , "Croatian" , "Czech" , "French" , "German" , "Hausa" , "Korean" , "Mandarin" , "Polish" , "Portuguese" , "Russian" , "Spanish" , "Swahili" , "Swedish" , "Thai" , "Turkish" , "Ukrainian" , "Vietnamese"]
	# languages=`stringArrayRemove {"Vietnamese"} $languages`;
	return languages


def currentTimeUnitToFPS():
	unit = cmds.currentUnit(q = True , time = True)
	fps = 0

	if unit == "game":
		fps = 15
	elif unit == "film":
		fps = 24
	elif unit == "pal":
		fps = 25
	elif unit == "ntsc":
		fps = 30
	elif unit == "show":
		fps = 48
	elif unit == "palf":
		fps = 50
	elif unit == "ntscf":
		fps = 60
	elif unit == "2fps":
		fps = 2
	elif unit == "3fps":
		fps = 3
	elif unit == "4fps":
		fps = 4
	elif unit == "5fps":
		fps = 5
	elif unit == "6fps":
		fps = 6
	elif unit == "8fps":
		fps = 8
	elif unit == "10fps":
		fps = 10
	elif unit == "12fps":
		fps = 12
	elif unit == "16fps":
		fps = 16
	elif unit == "20fps":
		fps = 20
	elif unit == "23.976fps":
		fps = 24.0 * 1000.0 / 1001.0
	elif unit == "29.97fps":
		fps = 30.0 * 1000.0 / 1001.0
	elif unit == "29.97df":
		fps = 30.0 * 1000.0 / 1001.0
	elif unit == "40fps":
		fps = 40
	elif unit == "47.952fps":
		fps = 48.0 * 1000.0 / 1001.0
	elif unit == "59.94fps":
		fps = 60.0 * 1000.0 / 1001.0
	elif unit == "75fps":
		fps = 75
	elif unit == "80fps":
		fps = 80
	elif unit == "100fps":
		fps = 100
	elif unit == "120fps":
		fps = 120
	elif unit == "125fps":
		fps = 125
	elif unit == "150fps":
		fps = 150
	elif unit == "200fps":
		fps = 200
	elif unit == "240fps":
		fps = 240
	elif unit == "250fps":
		fps = 250
	elif unit == "300fps":
		fps = 300
	elif unit == "375fps":
		fps = 375
	elif unit == "400fps":
		fps = 400
	elif unit == "500fps":
		fps = 500
	elif unit == "600fps":
		fps = 600
	elif unit == "750fps":
		fps = 750
	elif unit == "1200fps":
		fps = 1200
	elif unit == "1500fps":
		fps = 1500
	elif unit == "2000fps":
		fps = 2000
	elif unit == "3000fps":
		fps = 3000
	elif unit == "6000fps":
		fps = 6000
	elif unit == "44100fps":
		fps = 41000
	elif unit == "48000fps":
		fps = 48000

	return fps


alignerDir = asGetScriptLocation() + "/AdvancedSkeletonFiles/bin/montreal-forced-aligner"
aligner = alignerDir + "/bin/mfa_align"
if mel.eval('about -win'):
	aligner = alignerDir + "/bin/mfa_align.exe"
	print(aligner)
haveAligner = os.path.isfile(aligner)
languages = asAutoLipSyncLanguages


def asStripPath(path , numStrip):
	ret = ""
	tempString = []

	if path.startswith("//"):
		ret = "//"
	elif path.startswith("/"):
		ret = "/"

	tempString = path.split("/")
	for i in range(len(tempString) - numStrip):
		ret += tempString[i] + "/"

	return ret


def asGetTempDirectory():
	tempDirectory = os.environ['TEMP']
	folders = []
	if "~" in tempDirectory:
		folders = tempDirectory.split("/")
		tempDirectory = ""
		for i in range(len(folders)):
			if "~" in folders[i]:
				folders[i] = os.environ['USERNAME']
			tempDirectory += folders[i]
			if i < len(folders) - 1:
				tempDirectory += "/"
	return tempDirectory


def latinWriting(language):
	latin = 1
	# Bulgarian: Cyrillic alphabet
	# Korean: Hangul
	# Mandarin: Hanzi
	# Russian: Cyrillic alphabet
	# Thai: Thai script
	# Ukrainian: Cyrillic alphabet
	# Vietnamese: Vietnamese alphabet
	latinWritingLanguages = ["Bulgarian" , "Korean" , "Mandarin" , "Russian" , "Thai" , "Ukrainian" , "Vietnamese"]
	if language in latinWritingLanguages:
		latin = 0

	# Proceed with assuming all languages should be Romanized
	# latin = 1

	# checkBox can now choose this
	if not cmds.checkBox("asAutoLipSyncNonLatinCheckBox" , q = 1 , v = 1):
		latin = 0

	return latin


def asAutoLipSyncForceAlign(nameSpace):
	segmentReplacing = 0
	alwaysReCode = cmds.checkBox("asAutoLipSyncAlwaysReCodeCheckBox" , q = True , v = 1)  # 获取
	print(alwaysReCode)
	aPlayBackSliderPython = mel.eval('$tmpVar=$gPlayBackSlider')  # 获取时间轴信息
	timeRangeArray = cmds.timeControl(aPlayBackSliderPython , q = True , rangeArray = 1)
	print(timeRangeArray)
	if (timeRangeArray[1] - timeRangeArray[0]) > 1:
		segmentReplacing = 1
	print(segmentReplacing)
	fps = currentTimeUnitToFPS()  # 帧速率
	if fps < 1:
		fps = 1  # nameSpace = asNameSpaceFromUIName(input_string)#名字空间
	mfaDir = ''
	cmd = ''
	genDictCmd = ''
	ffMpegCmd = ''
	pythonCmd = ''
	uniDecoded = ""
	tempString = []
	languageMenuValue = cmds.optionMenu("asAutoLipSyncLanguageOptionMenu" , q = True , v = 1)
	# print languageMenuValue,"8888888888888888888"
	language = languageMenuValue.lower()  # 转成小写
	print(language , "8888888888888888888")
	aligner = cmds.text("asAutoLipSyncAlignerText" , q = True , l = 1)
	print(aligner)
	mfaDir = asStripPath(aligner , 2)
	lexicon = mfaDir + "bin/librispeech-lexicon.txt"
	print(lexicon)
	ffmpeg = mfaDir + "bin/ffmpeg.e"
	print(ffmpeg)
	if mel.eval("about -mac"):
		ffmpeg = mfaDir + "bin/ffmpeg"

	mfaGD = mfaDir + "bin/mfa_generate_dictionary"
	g2pFile = mfaDir + "pretrained_models/" + language + "_g2p.zip"
	languageZipFile = mfaDir + "pretrained_models/" + language + ".zip"  # 语言模型路径
	tempDir = asGetTempDirectory() + "/AdvancedSkeleton/autoLipSync/"  # 获取本地缓存路径
	audioNode = cmds.timeControl(aPlayBackSliderPython , q = True , s = 1)  # 获取时间轴的音频

	if not cmds.objExists(audioNode):
		cmds.error("No sound found. Make sure to import a sound file first")

	soundFile = cmds.getAttr(audioNode + ".filename")
	tempString = soundFile.split("/")
	soundFileBaseName = tempString[len(tempString) - 1]  # 音频文件
	tempString = soundFile.split(".")
	soundFileExt = tempString[len(tempString) - 1]
	forceSoundFile = tempDir + "input/align." + soundFileExt
	forceTextFile = tempDir + "input/align.txt"
	textGridFile = tempDir + "output/align.TextGrid"
	forceText = cmds.scrollField("asAutoLipSyncUIScrollField" , q = True , tx = 1)

	if not cmds.objExists(nameSpace + "FaceControlSet"):
		cmds.error(u"未检测到控制集。选择控制器")

	if not cmds.objExists(nameSpace + "ctrlPhonemes_M"):
		cmds.error(nameSpace + "ctrlPhonemes_M not found")

	if not cmds.file(aligner , q = True , ex = 1):
		cmds.error(u"缺少文件:\"" + aligner + "\"")
	genDictCmd = ''
	if language != "english":
		lexicon = tempDir + "sessionLexicon.txt"
		if (mel.eval("about -mac")) or (mel.eval("about -linux")):
			print("11111111111")
			genDictCmd = "\"" + mfaGD + "\" \"" + g2pFile + "\" \"" + tempDir + "input/\" \"" + lexicon + "\""
		else:
			print("2222222222")
			genDictCmd = "start/wait/I \"Generating Dictionary\" \"" + mfaGD + "\" \"" + g2pFile + "\" \"" + tempDir + "input/\" \"" + lexicon + "\""
	# print lexicon
	# print genDictCmd

	if (mel.eval("about -mac")) or (mel.eval("about -linux")):
		cmd = aligner + " -c " + tempDir + "input\\" + lexicon + language + tempDir + "output\\"
		ffMpegCmd = "start/wait/I Coding Audio" + ffmpeg + " -y -i " + soundFile
	else:
		cmd = 'start/wait/I "Force Aligning:" "%s" -c "%sinput/" "%s" %s "%soutput/"' % (aligner.replace("\\" , "/") , tempDir.replace("\\" , "/") , lexicon.replace("\\" , "/") , language , tempDir.replace("\\" , "/"))
		ffMpegCmd = 'start/wait/I "Coding Audio" "%s" -y -i "%s"' % (ffmpeg.replace("\\" , "/") , soundFile.replace("\\" , "/"))
		print(cmd)
		print(ffMpegCmd)  # / Starting Force Aligning:start/wait/I "Force Aligning" "C:/Users/pc/Downloads/AdvancedSkeleton/AdvancedSkeletonFiles/bin/montreal-forced-aligner/bin/mfa_align.exe" -c "C:/Users/pc/AppData/Local/Temp/AdvancedSkeleton/autoLipSync/input/" "C:/Users/pc/Downloads/AdvancedSkeleton/AdvancedSkeletonFiles/bin/montreal-forced-aligner/bin/librispeech-lexicon.txt" english "C:/Users/pc/AppData/Local/Temp/AdvancedSkeleton/autoLipSync/output/"  # // Successfully created:"C:/Users/pc/AppData/Local/Temp/AdvancedSkeleton/autoLipSync/output/align.TextGrid".
	if not os.path.exists(soundFile):
		cmds.error(u"不是有效的声音文件")
	if os.path.exists(tempDir + "output"):
		tempString = os.listdir(tempDir + "output")
		for file in tempString:
			os.remove(tempDir + "output/" + file)

	if "asAutoLipSyncNonLatinCheckBox" and not segmentReplacing:
		if os.path.exists(tempDir + "render"):
			tempString = os.listdir(tempDir + "render")
			for file in tempString:
				os.remove(tempDir + "render/" + file)

	if not os.path.exists(tempDir + "input"):
		os.makedirs(tempDir + "input")
	if not os.path.exists(tempDir + "output"):
		os.makedirs(tempDir + "output")
		os.shutil.copy(forceSoundFile , soundFile)
	# if segmentReplacing or alwaysReCode:
	#    if not os.path.exists(ffmpeg):
	#        asAutoLipSyncFfmpegDownload()
	if segmentReplacing:
		print(u"//在时间线滑块上找到分段选择，将音频修剪到所选内容.\n")
		ffMpegCmd += " -ss " + (timeRangeArray[0] / fps) + " -to " + (timeRangeArray[1] / fps) + " " + forceSoundFile
		print(u"// 开始修剪音频:" + ffMpegCmd + "\n")
		os.system(ffMpegCmd)
	if alwaysReCode:
		ffMpegCmd += " " + forceSoundFile
		print(u"// 启动ReCode Audio:" + ffMpegCmd + "\n")
		os.system(ffMpegCmd)
	print(ffMpegCmd , "0000000000000000000000000000000000000000000000000000000000")

	import unicodedata

	# def latinWriting(languageMenuValue, forceText, forceTextFile, asAutoLipSyncUIScrollField):
	if latinWriting(languageMenuValue):
		# Unidecode to transliterates any unicode string into the closest possible representation in ascii text.
		# open file > strip_accents > save file, in Py, so we do not need to pass the text as variable
		print(forceText)
		forceText = forceText.replace("`" , "")
		forceText = forceText.replace("'" , " ")
		forceText = forceText.replace("\n" , " ")

		def strip_accents(s):
			print("-----------------------------")
			return ''.join(c for c in unicodedata.normalize('NFD' , s) if unicodedata.category(c) != 'Mn')

		uniDecoded = strip_accents(forceText)
		print(uniDecoded)
		with open(forceTextFile , "w") as file:
			file.write(uniDecoded)

		if uniDecoded != forceText:
			cmds.scrollField("asAutoLipSyncUIScrollField" , e = True , tx = uniDecoded)

	if language != "english":
		print(u"// 正在启动生成词典:" + genDictCmd + "\n")
		if os.path.exists(lexicon):
			cmds.sysFile(lexicon , delete = 1)
		os.system(genDictCmd)
		if not os.path.exists(lexicon):
			cmds.error(u"创建词典失败:" + lexicon)
	print(forceText)
	if forceText != "":
		print(u"// Starting Force Aligning" + cmd + "\n")
		os.system(cmd)
	else:
		with open(textGridFile , "w") as file:
			fileId = file.read()
			print(fileId)

	if os.path.exists(textGridFile):
		print("// 已成功创建:" + textGridFile + ".\n")
	else:
		if os.path.exists(tempDir + "output/unaligned.txt"):
			with open(fileId , "r") as file:
				tempString = file.read()
				print(tempString + "\n")

		if cmds.confirmDialog(title = "Confirm" , message = "强制对齐失败。\n这可能是声音文件的兼容性问题。\n是否尝试重新编码声音文件？" , button = ["Yes" , "No"] , defaultButton = "Yes" , cancelButton = "No" , dismissString = "No") == "Yes":
			cmds.checkBox("asAutoLipSyncAlwaysReCodeCheckBox" , e = True , v = 1)
			asAutoLipSyncForceAlign(nameSpace)
			return

		if cmds.confirmDialog(title = "Confirm" , message = "Force Align Failed.\nThe language files might be incorrect,\nTry to re-download language files?" , button = ["Yes" , "No"] , defaultButton = "Yes" , cancelButton = "No" , dismissString = "No") == "Yes":
			os.remove(languageZipFile)
			os.remove(g2pFile)
			# asAutoLipSyncLanguageChanged()
			# asAutoLipSyncForceAlign(nameSpace)
			return
		cmds.error("创建失败:\"" + textGridFile + ".\n")

	asAutoLipSyncImport(nameSpace)



def asGetImConvertCmd():
	imConvertCmd = "imconvert"
	mayaLocation = os.getenv("MAYA_LOCATION")
	if os.path.exists(mayaLocation + "/bin/magick.exe") or os.path.exists(mayaLocation + "/bin/magick"):
		imConvertCmd = "magick"
	return imConvertCmd


def asGetTempDirectory():
	tempDirectory = os.environ['TEMP']
	folders = []
	if "~" in tempDirectory:
		folders = tempDirectory.split("/")
		tempDirectory = ""
		for i in range(len(folders)):
			if "~" in folders[i]:
				folders[i] = os.environ['USERNAME']
			tempDirectory += folders[i]
			if i < len(folders) - 1:
				tempDirectory += "/"
	return tempDirectory
def asAutoLipSyncPhonemeMapping(phone):
	phone = phone.upper()
	phoneme = ""
	if phone == "EY1":
		phoneme = "aaa"
	if phone == "Z":
		phoneme = "sss"
	if phone == "B":
		phoneme = "mbp"
	if phone == "AA2":
		phoneme = "aaa"
	if phone == "D":
		phoneme = "lntd"
	if phone == "IY0":
		phoneme = "tth"
	if phone == "K":
		phoneme = "gk"
	if phone == "AO2":
		phoneme = "ohh"
	if phone=="R"	:
		phoneme="rrr"
	if phone=="T"	:
		phoneme="lntd"
	if phone=="G"	:
		phoneme="gk"
	if phone=="AH0"  :
		phoneme="ahh"
	if phone=="OY1"  :
		phoneme="ohh"
	if phone=="N"	:
		phoneme="lntd"
	if phone=="L"	:
		phoneme="lntd"
	if phone=="M"	:
		phoneme="mbp"
	if phone=="AY1"  :
		phoneme="ahh"
	if phone=="OW2"  :
		phoneme="ohh"
	if phone=="S"	:
		phoneme="sss"
	if phone=="P"	:
		phoneme="mbp"
	if phone=="EH2"  :
		phoneme="eh"
	if phone=="IY1"  :
		phoneme="iee"
	if phone=="AY2"  :
		phoneme="aaa"
	if phone=="OW1"  :
		phoneme="ohh"
	if phone=="ER0"  :
		phoneme="schwa"
	if phone=="UW1"  :
		phoneme="ohh"
	if phone=="W"	:
		phoneme="www"
	if phone=="DH"   :
		phoneme="lntd"
	if phone=="JH"   :
		phoneme="ssh"
	if phone=="IH1"  :
		phoneme="iee"
	if phone=="IH0"  :
		phoneme="iee"
	if phone=="NG"   :
		phoneme="gk"
	if phone=="IH2"  :
		phoneme="eh"
	if phone=="V"	:
		phoneme="schwa"
	if phone=="AA1"  :
		phoneme="ohh"
	if phone=="TH"   :
		phoneme="lntd"
	if phone=="ZH"   :
		phoneme="ssh"
	if phone=="AE2"  :
		phoneme="aaa"
	if phone=="SH"   :
		phoneme="ssh"
	if phone=="EH1"  :
		phoneme="eh"
	if phone=="AA0"  :
		phoneme="aaa"
	if phone=="F"	:
		phoneme="fff"
	if phone=="AW1"  :
		phoneme="www"
	if phone=="AE1"  :
		phoneme="aaa"
	if phone=="OW0"  :
		phoneme="ohh"
	if phone=="AW2"  :
		phoneme="aaa"
	if phone=="EY2"  :
		phoneme="eh"
	if phone=="EY0"  :
		phoneme="aaa"
	if phone=="AE0"  :
		phoneme="aaa"
	if phone=="IY2"  :
		phoneme="iee"
	if phone=="CH"   :
		phoneme="ssh"
	if phone=="ER1"  :
		phoneme="ahh"
	if phone=="EH0"  :
		phoneme="ahh"
	if phone=="UW2"  :
		phoneme="ohh"
	if phone=="AH1"  :
		phoneme="ohh"
	if phone=="HH"   :
		phoneme="schwa"
	if phone=="AH2"  :
		phoneme="ahh"
	if phone=="AO0"  :
		phoneme="ahh"
	if phone=="OY2"  :
		phoneme="ohh"
	if phone=="OY0"  :
		phoneme="ohh"
	if phone=="UH1"  :
		phoneme="ohh"
	if phone=="AO1"  :
		phoneme="ohh"
	if phone=="UW0"  :
		phoneme="ohh"
	if phone=="Y"	:
		phoneme="uuu"
	if phone=="AW0"  :
		phoneme="aaa"
	if phone=="AY0"  :
		phoneme="ahh"
	if phone=="ER2"  :
		phoneme="ohh"
	if phone=="UH0"  :
		phoneme="uuu"
	if phone=="UH2":
		phoneme="ohh"
	return phoneme
def asAutoLipSyncImport(nameSpace):
	nameSpace = "A10_C0350WJY_RIG:"
	gMainProgressBar = mel.eval('$tmpVar=$gMainProgressBar')
	gPlayBackSlider = "PlayBackSlider"
	gCurrentTimeCmdValueTable = []
	segmentReplacing = 0
	aPlayBackSliderPython = mel.eval('$tmpVar=$gPlayBackSlider')  # 获取时间轴信息
	timeRangeArray = cmds.timeControl(aPlayBackSliderPython , q = True , rangeArray = 1)
	fps = currentTimeUnitToFPS()
	if fps < 1:
		fps = 1
	nonLatin = cmds.checkBox("asAutoLipSyncNonLatinCheckBox" , q = True , v = 1)  # False
	wordsSection , phonesSection , fileId = 0 , 0 , 0
	autoBlink = cmds.checkBox("asAutoLipSyncBlinkCheckBox" , q = True , v = 1)  # True
	autoGlimpse = cmds.checkBox("asAutoLipSyncGlimpseCheckBox" , q = True , v = 1)  # True
	autoEyeBrows = cmds.checkBox("asAutoLipSyncEyeBrowsCheckBox" , q = True , v = 1)  # True
	autoHead = cmds.checkBox("asAutoLipSyncHeadCheckBox" , q = True , v = 1)  # True
	lastKeyFrameNr , nextBlinkTriggFrameNr , nextGlipseTriggFrameNr , nextHeadTriggFrameNr , wordNr = 0 , 0 , 0 , 0 , 0
	if not cmds.objExists(nameSpace + "FKHead_M"):
		autoHead = 0
	prePhoneTime = cmds.floatField("asAutoLipSyncPhonemeInFloatField" , q = True , v = 1) * fps
	postPhoneTime = cmds.floatField("asAutoLipSyncPhonemeOutFloatField" , q = True , v = 1) * fps
	sequenceStart = -1
	sequenceEnd = -1
	wordSpace = 0.25  # 0.25*$fps
	scale = 1.5
	xMin , xMax , segRepOffset , keyValue , previousKeyTime = 0 , 0 , 0 , 0 , 0
	wordStarts , wordEnds , phoneStarts , phoneEnds , bb , keyTimes , pos , pos1 , pos2 = [] , [] , [] , [] , [] , [] , [] , [] , []
	aligner = cmds.text("asAutoLipSyncAlignerText" , q = True , l = 1)
	tempDir = asGetTempDirectory() + "/AdvancedSkeleton/autoLipSync/"
	textGridFile = tempDir + "output/align.TextGrid"
	nextLine , para , value , pythonCmd , fileRead , font , imConvertCmdLine = "" , "" , "" , "" , "" , "" , ""
	imConvertCmd = asGetImConvertCmd()
	tempString , words , phones , missingPhoneParts , letters , deleteObjs , texts , chars = [] , [] , [] , [] , [] , [] , [] , []
	currentTimeUnit = cmds.currentUnit(q = True , t = True)
	audioNode = cmds.timeControl(aPlayBackSliderPython , q = True , s = 1)
	languageMenuValue = cmds.optionMenu("asAutoLipSyncLanguageOptionMenu" , q = True , v = 1)
	language = languageMenuValue.lower()
	offset = cmds.getAttr(audioNode + ".offset") / fps

	if not cmds.objExists(nameSpace + "ctrlPhonemes_M"):
		cmds.error(nameSpace + "ctrlPhonemes_M not found")

	if cmds.objExists(nameSpace + "FaceFitSkeletonHeightShape"):
		pos1 = cmds.xform(nameSpace + "FaceFitSkeletonHeightShape.cv[5]" , q = True , ws = True , t = 1)
		pos2 = cmds.xform(nameSpace + "FaceFitSkeletonShape.cv[5]" , q = True , ws = True , t = 1)
		scale = pos1[1] - pos2[1]

	if (timeRangeArray[1] - timeRangeArray[0]) > 1 and cmds.objExists(nameSpace + "subTitles"):
		segmentReplacing = 1

	if segmentReplacing:
		cmds.select(cl = True)
		pos = cmds.xform(nameSpace + "subTitlesArrowShape.cv[3]" , q = True , ws = True , t = 1)
		texts = cmds.listRelatives(nameSpace + "subTitlesRoller" , c = 1 , type = "transform")
		cmds.currentTime(timeRangeArray[0])
		previousKeyTime = cmds.findKeyframe(nameSpace + "subTitlesRoller.tx" , q = 1 , which = "previous" , time = 1)

		for i in range(len(texts)):
			chars = cmds.listRelatives(c = True , type = "transform" , ad = True , f = texts[i])
			print
			chars
			if nonLatin:
				chars[0] = texts[i]
			for y in range(len(chars)):
				if (cmds.getAttr(t = (cmds.getAttr(previousKeyTime , (nameSpace + "subTitlesRoller.tx")) * -1 , cmds.getAttr((texts[i] + ".tx"))))):
					cmds.select(add = True , objects = texts[i])

		if len(cmds.ls(selection = True)) > 0:
			cmds.delete()

		if cmds.objExists(nameSpace + "subTitlesRoller"):
			cmds.cutKey(time = (timeRangeArray[0] + ":99999") , attribute = "translateX" , option = "keys" , clear = True)
		cmds.cutKey(time = (timeRangeArray[0] + ":99999") , option = "keys" , clear = True , attribute = (nameSpace + "ctrlPhonemes_M"))

	# if not mel.eval('stringArrayCount("sec", %s)'%(gCurrentTimeCmdValueTable)) and mel.eval('exists( workingTimeUtil)'):
	#	cmds.optionVar(iv=("hideNoFPSFramerate", 0))
	#	cmds.evalDeferred("source workingTimeUtil")

	cmds.currentUnit(t = "sec")
	# cmds.evalDeferred('catchQuiet(\'currentUnit -t {}\')'.format(currentTimeUnit))

	if cmds.currentUnit(q = True , t = True) == "sec":
		cmds.currentUnit(t = "film")
	if segmentReplacing:
		segRepOffset = cmds.currentTime(q = 1)
	if segmentReplacing:
		if cmds.objExists("subTitles_parentConstraint1"):
			cmds.delete("subTitles_parentConstraint1")
		if cmds.objExists(nameSpace + "subTitles"):
			cmds.xform(ws = True , t = [0 , 0 , 0] , ro = [0 , 0 , 0] , s = [1 , 1 , 1] , object = (nameSpace + "subTitles"))
	else:
		deleteObjs = [nameSpace + "subTitles" , nameSpace + "subTitlesExp" , nameSpace + "subTitlesBox" , nameSpace + "subTitlesArrow" , nameSpace + "subTitlesBoxMPD"]
		for i in range(len(deleteObjs)):
			if cmds.objExists(deleteObjs[i]):
				cmds.delete(deleteObjs[i])
		cmds.createNode("transform" , name = nameSpace + "subTitles")  # createNode -n ($nameSpace+"subTitles") transform;
		cmds.createNode("transform" , name = nameSpace + "subTitlesRoller" , parent = nameSpace + "subTitles")  # createNode -n ($nameSpace+"subTitlesRoller") -p ($nameSpace+"subTitles") transform;
		tempString = cmds.curve(d = 1 , p = [(-4 , 1.25 , 0) , (-4 , -0.5 , 0) , (4 , -0.5 , 0) , (4 , 1.25 , 0) , (-4 , 1.25 , 0)] , k = [0 , 1 , 2 , 3 , 4])  # $tempString[0]=`curve -d 1 -p -4 1.25 0 -p -4 -0.5 0 -p 4 -0.5 0 -p 4 1.25 0 -p -4 1.25 0 -k 0 -k 1 -k 2 -k 3 -k 4`;
		cmds.rename(tempString , nameSpace + "subTitlesBox")  # rename $tempString[0] ($nameSpace+"subTitlesBox");
		cmds.setAttr(nameSpace + "subTitlesBoxShape.overrideEnabled" , 1)  # setAttr ($nameSpace+"subTitlesBoxShape.overrideEnabled") 1;
		cmds.setAttr(nameSpace + "subTitlesBoxShape.overrideColor" , 13)
		tempString = cmds.curve(d = 1 , p = [(0 , 0.65 , 0) , (0.127 , 1.2 , 0) , (-0.127 , 1.2 , 0) , (0 , 0.65 , 0)] , k = [0 , 1 , 2 , 3])  # $tempString[0]=`curve -d 1 -p 0 0.65 0 -p 0.127 1.2 0 -p -0.127 1.2 0 -p 0 0.65 0 -k 0 -k 1 -k 2 -k 3`;
		cmds.parent(nameSpace + "subTitlesBox" , nameSpace + "subTitles")  # parent ($nameSpace+"subTitlesBox") ($nameSpace+"subTitles");
		cmds.addAttr(nameSpace + "subTitlesBox" , k = 1 , ln = "textVisCenter" , at = "double" , dv = 4.5)  # addAttr -k 1 -ln textVisCenter -at double -dv 4.5 ($nameSpace+"subTitlesBox");
		cmds.addAttr(nameSpace + "subTitlesBox" , k = 1 , ln = "textVisLenght" , at = "double" , dv = 8)  # addAttr -k 1 -ln textVisLenght -at double -dv 8 ($nameSpace+"subTitlesBox");
		cmds.createNode("multiplyDivide" , n = nameSpace + "subTitlesBoxMPD")  # createNode -n ($nameSpace+"subTitlesBoxMPD") multiplyDivide;
		cmds.connectAttr(nameSpace + "subTitlesBox.sx" , nameSpace + "subTitlesBoxMPD.input1X")  # connectAttr ($nameSpace+"subTitlesBox.sx") ($nameSpace+"subTitlesBoxMPD.input1X");
		cmds.connectAttr(nameSpace + "subTitlesBox.sx" , nameSpace + "subTitlesBoxMPD.input1Y")  # connectAttr ($nameSpace+"subTitlesBox.sx") ($nameSpace+"subTitlesBoxMPD.input1Y");
		cmds.setAttr(nameSpace + "subTitlesBoxMPD.input2" , 4 , 8 , 0 , type = "float3")  # setAttr ($nameSpace+"subTitlesBoxMPD.input2") -type float3 4 8 0;
		cmds.connectAttr(nameSpace + "subTitlesBoxMPD.outputX" , nameSpace + "subTitlesBox.textVisCenter")  # connectAttr ($nameSpace+"subTitlesBoxMPD.outputX") ($nameSpace+"subTitlesBox.textVisCenter");
		cmds.connectAttr(nameSpace + "subTitlesBoxMPD.outputY" , nameSpace + "subTitlesBox.textVisLenght")  # connectAttr ($nameSpace+"subTitlesBoxMPD.outputY") ($nameSpace+"subTitlesBox.textVisLenght");
		cmds.rename(tempString , nameSpace + "subTitlesArrow")  # rename $tempString[0] ($nameSpace+"subTitlesArrow");
		cmds.setAttr(nameSpace + "subTitlesArrowShape.overrideEnabled" , 1)  # setAttr ($nameSpace+"subTitlesArrowShape.overrideEnabled") 1;
		cmds.setAttr(nameSpace + "subTitlesArrowShape.overrideColor" , 13)  # setAttr ($nameSpace+"subTitlesArrowShape.overrideColor") 13;
		cmds.parent(nameSpace + "subTitlesArrowShape" , nameSpace + "subTitlesBox" , add = 1 , s = 1)  # parent -add -s ($nameSpace+"subTitlesArrowShape") ($nameSpace+"subTitlesBox");
		cmds.delete(nameSpace + "subTitlesArrow")  # delete ($nameSpace+"subTitlesArrow");
		tempString = cmds.listConnections(nameSpace + "ctrlPhonemes_M" , s = 1 , d = 0 , type = "animCurve")  # $tempString=`listConnections -s 1 -d 0 -type animCurve ($nameSpace+"ctrlPhonemes_M")`;
		print(tempString)
		# cmds.parentConstraint(nameSpace + "ctrlBox" , nameSpace + "subTitlesRoller" , mo = True)
		if tempString:  # if (size($tempString)) delete $tempString;
			cmds.delete(tempString)

			tempString = cmds.listAttr(nameSpace + "ctrlPhonemes_M" , ud = True)
			for attr in tempString:
				if not cmds.getAttr(nameSpace + "ctrlPhonemes_M." + attr , lock = True):
					cmds.setAttr(nameSpace + "ctrlPhonemes_M." + attr , 0)
			if cmds.attributeQuery("jaw" , node = nameSpace + "ctrlPhonemes_M" , exists = True):
				cmds.setAttr(nameSpace + "ctrlPhonemes_M.jaw" , 0.25)
				cmds.setAttr(nameSpace + "ctrlPhonemes_M.lip" , 0.25)
				if cmds.objExists("asFaceBS"):
					cmds.setAttr(nameSpace + "ctrlPhonemes_M.jaw" , 1)
					cmds.setAttr(nameSpace + "ctrlPhonemes_M.lip" , 1)

	with open(textGridFile , 'r') as fileId:
		for nextLine in fileId:
			line = nextLine.strip()
			if line:
				tempString = line.split(" = ")
				if len(tempString) >= 2:
					para = tempString[0]
					value = tempString[1]
					# print(para)
					# print(value)

					if sequenceStart == -1 and para == "xmin":
						sequenceStart = float(value) * fps

					if sequenceEnd == -1 and para == "xmax":
						sequenceEnd = float(value) * fps

					if para == "name":
						if value == "\"words\"":
							wordsSection = 1
						if value == "\"phones\"":
							phonesSection = 1
							wordsSection = 0

					if para == "xmin":
						xMin = float(value)
					if para == "xmax":
						xMax = float(value)

					if wordsSection and para == "text":
						tempString[0] = value.replace("\"" , "")
						if tempString[0] != "":
							words.append(tempString[0])
							wordStarts.append((xMin + segRepOffset + offset) * fps)
							wordEnds.append((xMax + segRepOffset + offset) * fps)

					if phonesSection and para == "text":
						tempString[0] = value.replace("\"" , "")
						if tempString[0] != "":
							phones.append(tempString[0])
							phoneStarts.append((xMin + segRepOffset + offset) * fps)
							phoneEnds.append((xMax + segRepOffset + offset) * fps)

	fileId.close()

	for i in range(len(words)):
		if words[i] == "<unk>":
			words[i] = "***"
	if not segmentReplacing:
		cmds.playbackOptions(min = (sequenceStart + offset) , ast = (sequenceStart + offset) , aet = (sequenceEnd + offset) , max = (sequenceEnd + offset))

	# setKeyframe command
	cmds.setKeyframe(nameSpace + "subTitlesRoller" , at = "tx" , v = 0 , t = 0 , itt = "linear" , ott = "linear")

	# for loop
	wordNr = 0
	for i in range(9999):
		if not cmds.objExists(nameSpace + "text" + str(i)):
			break
		wordNr = i
	if nonLatin:
		if not os.path.exists(tempDir + "render"):
			os.makedirs(tempDir + "render")
		wordsSection = 0
		# wordNr = wordNr
		searchfile = open(textGridFile , 'r')
		for line in searchfile:
			if line.find('name = \"words\"') != -1:
				wordsSection = 1
			if line.find('name = \"phones\"') != -1:
				wordsSection = 0
			if wordsSection == 1:
				if line.find('text = ') != -1:
					word = line.split()[2].replace('\"' , '')
					if word == '':
						continue
					tempDir + "render/word" + str(wordNr) + ".txt"
					wordFile = open(tempDir + "render/word" + str(wordNr) + ".txt" , 'w')
					wordFile.write(word)
					wordFile.close()
					wordNr = wordNr + 1
		searchfile.close()

	if nonLatin:
		cmds.progressBar(gMainProgressBar , e = True , ep = 1)
	cmds.progressBar(gMainProgressBar , e = True , st = "Reading Data" , bp = 1 , ii = 1 , min = 0 , max = (len(words) + 1))
	for i in range(len(words)):
		cmds.progressBar(gMainProgressBar , e = True , s = 1)
		if cmds.progressBar(gMainProgressBar , q = True , ic = 1):
			cmds.error("Interrupted")
		cmds.currentTime(wordStarts[i])
		if nonLatin:
			font = "arial"
		if language == "thai":
			font = "tahoma"
		if language == "korean":
			font = "Malgun-Gothic"
		imConvertCmdLine = imConvertCmd + " -background black -fill white -font " + font + " -pointsize 72 label:@" + tempDir + "render/word" + str(wordNr) + ".txt " + tempDir + "render/word" + str(wordNr) + ".png"
		os.system(imConvertCmdLine)
		tempString = cmds.ls((nameSpace + "text*" + str(wordNr)))
		for y in range(len(tempString)):
			if cmds.objExists(tempString[y]):
				cmds.delete(tempString[y])
			cmds.polyPlane(n = nameSpace + "text" + str(wordNr) , w = 1 , h = 1 , sx = 1 , sy = 1 , ax = [0 , 0 , 1] , cuv = 2 , ch = 0)
			cmds.shadingNode("surfaceShader",n = nameSpace + "textShader" + str(wordNr) , asShader = 1)
			cmds.sets(renderable = True , noSurfaceShader = True , empty = True , name = (nameSpace + "textSG" + str(wordNr)))
			cmds.connectAttr(nameSpace + "textShader" + str(wordNr) + ".outColor" , nameSpace + "textSG" + str(wordNr) + ".surfaceShader" ,f=1)
			cmds.sets(nameSpace + "text" + str(wordNr) , e = True , forceElement = nameSpace + "textSG" + str(wordNr))
			cmds.createNode("file" , n = nameSpace + "textFile" + str(wordNr))
			cmds.connectAttr(nameSpace + "textFile" + str(wordNr) + ".outColor" , nameSpace + "textShader" + str(wordNr) + ".outColor" , force = 1)
			cmds.setAttr((nameSpace + "textFile" + str(wordNr) + ".fileTextureName") , (tempDir + "render/word" + str(wordNr) + ".png") , type = "string")
			cmds.move(0.5 , 0 , 0 , nameSpace + "text" + str(wordNr) + ".vtx[0:99]" , r = True , ws = True , wd = 1)
			cmds.scale(len(words[i]) / 2.25 , 1 , 1 , nameSpace + "text" + str(wordNr) + ".vtx[0:99]" , r = True , p = [0 , 0 , 0])
		else:
			tempString = cmds.textCurves( f = "Times New Roman|wt:50|sz:28" , t = words[i])
			cmds.delete(cmds.ls(type = "makeTextCurves"))
			cmds.rename(tempString[0] , nameSpace + "text" + str(wordNr))
		cmds.setAttr(nameSpace + "text" + str(wordNr) + ".tx" , wordSpace)
		cmds.parent(nameSpace + "text" + str(wordNr) , nameSpace + "subTitlesRoller")
		cmds.setKeyframe(nameSpace + "subTitlesRoller.tx" , itt = "linear" , ott = "linear" , t = wordStarts[i] , v = (cmds.getAttr((nameSpace + "subTitlesRoller.tx")) - wordSpace))
		bb = cmds.xform(nameSpace + "text" + str(wordNr) , q = 1 , ws = 1 , bb = 1)
		keyValue = cmds.getAttr(nameSpace + "subTitlesRoller.tx") - (float(bb[0]) + float(bb[3]))
		cmds.setKeyframe(nameSpace + "subTitlesRoller.tx" , itt = "linear" , ott = "linear" , t = wordEnds[i] , v = keyValue)
		wordNr += 1
	for i in range(len(phones)):
		if (phones[i] == "sil" or phones[i] == "sp" or phones[i] == "spn"):
			continue
		# if (language == "english"):
		phoneme = asAutoLipSyncPhonemeMapping(phones[i])
		# else:
		#	 phoneme = substring(language, 0, 3) + "_" + asPhonemeTranslate(phones[i], 0)
		if phoneme == "" or not cmds.attributeQuery(phoneme,n = nameSpace + "ctrlPhonemes_M" ,exists = True):
			if not phoneme in missingPhoneParts:
				missingPhoneParts.append("Phoneme:\"" + phoneme + "\", from the phone:	\"" + phones[i] + "\"")
			continue
		cmds.setKeyframe(nameSpace + "ctrlPhonemes_M." + phoneme, v = 0 , t = phoneStarts[i] - prePhoneTime )
		cmds.setKeyframe(nameSpace + "ctrlPhonemes_M." + phoneme,v = 10 , t = (phoneStarts[i] + phoneEnds[i]) / 2.0 )
		cmds.setKeyframe(nameSpace + "ctrlPhonemes_M." + phoneme,v = 0 , t = phoneEnds[i] + postPhoneTime)

	if len(missingPhoneParts) > 0:
		print("Found the following phonemes, that are not mapped to the current FaceSetup:")
		print(missingPhoneParts)
	cmds.progressBar(gMainProgressBar,e = True , ep = 1)
	cmds.currentTime(0)

	#if not cmds.currentUnit(q = True , t = True) == "sec":
	#	cmds.currentUnit(t = currentTimeUnit)

	cmds.currentTime(0)
	tempString = cmds.listRelatives(nameSpace + "subTitlesRoller",ad = True , type = "transform" , f = 1)
	for i in range(len(tempString)):
		if not tempString[i].startswith("Char_") and not nonLatin:
			continue
		letters.append(tempString[i])

	bb = cmds.xform(nameSpace + "subTitlesBox",q = True , ws = True , bb = 1)
	boxWidth = (bb[3] - bb[0]) / cmds.getAttr(nameSpace + "subTitles.sx")

	if nameSpace != "" and cmds.objExists("subTitlesRoller_translateX"):
		cmds.rename("subTitlesRoller_translateX" , nameSpace + "subTitlesRoller_translateX")

	keyTimes = cmds.keyframe(nameSpace + "subTitlesRoller_translateX",q = True , tc =1)
	lastKeyFrameNr = keyTimes[-1]
	cmds.progressBar(gMainProgressBar,e = True , st = "Animating text visibility" , bp = True , min = 0 , max = lastKeyFrameNr + 1)
	#letters = cmds.sort(letters)

	for y in range(len(letters)):
		if cmds.objExists((letters[y] + "PMA")):
			continue
		cmds.createNode("plusMinusAverage" , n = (letters[y] + "PMA"))
		cmds.connectAttr((nameSpace + "subTitlesRoller_translateX.output") , (letters[y] + "PMA.input1D[1]") , f = True)
		cmds.connectAttr((nameSpace + "subTitlesBox.textVisCenter") , (letters[y] + "PMA.input1D[2]") , f = True)
		bb = cmds.xform(q = True , ws = True , bb = letters[y])
		cmds.setAttr((letters[y] + "PMA.input1D[0]") , (bb[0] + 0.5))
		cmds.createNode("clamp" , n = (letters[y] + "Clamp"))
		cmds.connectAttr((letters[y] + "PMA.output1D") , (letters[y] + "Clamp.inputR") , f = True)
		cmds.setAttr((letters[y] + "Clamp.maxR") , 1000)
		cmds.createNode("condition" , n = (letters[y] + "Condition"))
		cmds.setAttr((letters[y] + "Condition.operation") , 2)
		cmds.connectAttr((letters[y] + "Clamp.outputR") , (letters[y] + "Condition.firstTerm") , f = True)
		cmds.connectAttr((letters[y] + "Clamp.outputR") , (letters[y] + "Condition.colorIfFalseR") , f = True)
		cmds.connectAttr((nameSpace + "subTitlesBox.textVisLenght") , (letters[y] + "Condition.secondTerm") , f = True)
		cmds.connectAttr((letters[y] + "Condition.outColorR") , (letters[y] + ".v") , f = True)

	#字幕对齐到头部
	bb = cmds.xform(nameSpace + "subTitles",q = True , ws = True , bb = 1)
	cmds.setAttr((nameSpace + "subTitles.s") , scale / 10.0 , scale / 10.0 , scale / 10.0 , type = "float3")
	bb = cmds.xform(nameSpace+"ctrlBox",q = True , ws = True , bb = 1)
	bb2 = cmds.xform(nameSpace+"ctrlPhonemes_M",q = True , ws = True , bb = 1)
	bb3 = cmds.xform(nameSpace + "subTitlesBox",q = True , ws = True , bb = 1)
	cmds.xform(nameSpace + "subTitles",ws = True , t = [bb[3] + bb3[3] * 1.2 , bb2[1] , bb[5]] )
	cmds.parentConstraint((nameSpace + "ctrlBox") , (nameSpace + "subTitles") , mo = True)

	if segmentReplacing:
		cmds.select(r = (nameSpace + "subTitles"))
		cmds.currentTime(timeRangeArray[0])
		cmds.dgdirty(a = True)
	if autoBlink:
		tempString = cmds.listConnections((nameSpace + "ctrlEye_R") , (nameSpace + "ctrlEye_L"),s = True , d = False , type = "animCurve" , shapes = True )
		if len(tempString) > 0:
			cmds.delete(tempString)

	if autoGlimpse:
		tempString = cmds.listConnections((nameSpace + "Eye_R") , (nameSpace + "Eye_L"),s = True , d = False , type = "animCurve" , shapes = True  )
		if len(tempString) > 0:
			cmds.delete(tempString)

	if autoHead:
		tempString = cmds.listConnections((nameSpace + "FKHead_M"),s = True , d = False , type = "animCurve"  )
		if len(tempString) > 0:
			cmds.delete(tempString)

	if autoBlink:
		tempString = cmds.listConnections( (nameSpace + "ctrlEye_R") , (nameSpace + "ctrlEye_L"),s = True , d = False , type = "animCurve" , shapes = True)
		if len(tempString) > 0:
			cmds.delete(tempString)

	if autoHead:
		cmds.setAttr((nameSpace + "AimEye_M.follow") , 0)
	import random
	nextBlinkTriggFrameNr = keyTimes[0] + random.randint(25 , 40)
	nextGlipseTriggFrameNr = keyTimes[0] + random.randint(25 , 40)
	nextHeadTriggFrameNr = keyTimes[0] + random.randint(80 , 100)
	'''
	for i in range(1 , int(cmds.playbackOptions(q = True , max = True))):
		if i < keyTimes[0]:
			continue
		if autoBlink and i == nextBlinkTriggFrameNr:
			nextBlinkTriggFrameNr = i + random.randint(50 , 250)
			cmds.setKeyframe(t = i , v = 1.5 , attribute = (nameSpace + "ctrlEye_L.blink") , (nameSpace + "ctrlEye_R.blink"))
			cmds.setKeyframe(t = (i + 1) , v = 10 , attribute = (nameSpace + "ctrlEye_L.blink") , (nameSpace + "ctrlEye_R.blink"))
			cmds.setKeyframe(t = (i + 3) , v = 10 , attribute = (nameSpace + "ctrlEye_L.blink") , (nameSpace + "ctrlEye_R.blink"))
			cmds.setKeyframe(t = (i + 6) , v = 1.5 , attribute = (nameSpace + "ctrlEye_L.blink") , (nameSpace + "ctrlEye_R.blink"))
	'''

def asAutoLipSyncLanguageChanged():
	haveLanguage = 1
	languageMenuValue = cmds.optionMenu("asAutoLipSyncLanguageOptionMenu" , query = True , value = True)
	language = languageMenuValue.lower()
	languageZip = language + ".zip"
	sLoc = cmds.asGetScriptLocation()
	curl = os.path.join(sLoc , "AdvancedSkeletonFiles" , "bin" , "curl.e")
	zip = os.path.join(sLoc , "AdvancedSkeletonFiles" , "bin" , "7za.e")
	binDir = os.path.join(sLoc , "AdvancedSkeletonFiles" , "bin")
	aligner = cmds.textField("asAutoLipSyncAlignerText" , query = True , label = True)
	zipFileUrl = ""
	tempString = []
	languageZipFiles = []
	pretrainedModelsDir = os.path.dirname(aligner) + "pretrained_models/"
	phonemes = cmds.asAutoLipSyncLanguagePhonemes(language)

	# latinWriting
	if cmds.latinWriting(languageMenuValue):
		cmds.button("asAutoLipSyncUIButton" , edit = True , enable = True)
		cmds.scrollField("asAutoLipSyncUIScrollField" , edit = True , enable = False)
	else:
		cmds.button("asAutoLipSyncUIButton" , edit = True , enable = False)
		cmds.scrollField("asAutoLipSyncUIScrollField" , edit = True , enable = True)

	# ensure we have the Phonemes for the language
	languageZipFiles = cmds.getFileList(folder = pretrainedModelsDir , files = True , directory = True)
	if languageZip not in languageZipFiles:
		result = cmds.confirmDialog(title = "Confirm" , message = "Download files for \"" + language + "\" language?" , button = ["Yes" , "No"] , defaultButton = "Yes" , cancelButton = "No" , dismissString = "No")
		if result == "Yes":
			haveLanguage = 0
		else:
			cmds.optionMenu("asAutoLipSyncLanguageOptionMenu" , edit = True , value = "English")

	# save this as the new `default` language
	cmds.optionVar(stringValue = ["asAutoLipSyncLanguage" , languageMenuValue])

	if haveLanguage:
		return

	if not os.path.exists(pretrainedModelsDir):
		cmds.error("Folder not found: " + pretrainedModelsDir)

	# download language files
	for a in range(2):
		if a == 0:
			languageZip = language + ".zip"
			zipFileUrl = "https://github.com/MontrealCorpusTools/mfa-models/raw/main/acoustic/" + languageZip
		if a == 1:
			languageZip = language + "_g2p.zip"
			zipFileUrl = "https://github.com/MontrealCorpusTools/mfa-models/raw/main/g2p/1.0/" + languageZip

		if language == "mandarin":
			zipFileUrl = "https://github.com/MontrealCorpusTools/mfa-models/raw/main/g2p/1.0/" + language + "_pinyin_g2p.zip"  # _pinyin variant

		if language == "korean":
			zipFileUrl = "https://github.com/MontrealCorpusTools/mfa-models/raw/main/g2p/1.0/" + language + "_jamo_g2p.zip"  # _jamo variant (not hangul)

		if cmds.about(mac = True) or cmds.about(linux = True):
			cmd = "curl -k -L -o " + os.path.join(pretrainedModelsDir , languageZip) + " " + zipFileUrl
			subprocess.call(cmd , shell = True)
		else:
			cmd = 'start/wait/I "Downloading" "' + curl + '" -k -L -o "' + os.path.join(pretrainedModelsDir , languageZip) + '" ' + zipFileUrl
			print("// Starting Download:" + cmd + "\n")
			subprocess.call(cmd , shell = True)


nameSpace = "A10_C0350WJY_RIG:"
asAutoLipSyncForceAlign(nameSpace)
